/**
* @project admin-go-api
* @name times
* @descriptions 时间工具类
* @author 寒锋
* @date 2023-12-14 15:48:03
 */

package util

import (
	"database/sql/driver"
	"fmt"
	"time"
)

type HTime struct {
	time.Time
}

var (
	formatTime = "2006-01-02 15:04:05"
)

// MarshalJSON 将 HTime 类型的时间值转化为一个特定格式的 JSON 字符串。
// 它将时间按照 formatTime 的格式进行格式化，并返回格式化后的字节切片
func (t HTime) MarshalJSON() ([]byte, error) {
	formatted := fmt.Sprintf("\"%s\"", t.Format(formatTime))
	return []byte(formatted), nil
}

// UnmarshalJSON 从 JSON 数据中解析出时间值，并赋给 HTime 类型的实例。
// 它首先根据给定的格式（即 formatTime）解析传入的字节切片数据， 然后将解析得到的时间赋值给 HTime 结构体的实例
func (t *HTime) UnmarshalJSON(data []byte) (err error) {
	now, err := time.ParseInLocation(`"`+formatTime+`"`, string(data),
		time.Local)
	*t = HTime{Time: now}
	return
}

// Value 将 HTime 类型的时间值转化为一个满足 driver.Value 接口的值。
// 如果时间值是有效的（即不是零时间），则返回该时间值；否则返回 nil。
// 这个方法通常用于数据库驱动程序，以便将时间值插入或检索到数据库中。
func (t HTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	if t.Time.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return t.Time, nil
}

// Scan 从数据库中扫描时间值，并将其赋给 HTime 类型的实例。
// 如果扫描的值是一个有效的时间值，则将其赋值给 HTime 结构体的实例；否则返回一个错误。
// 这个方法通常与数据库驱动程序一起使用，以便从数据库中检索时间值。
func (t *HTime) Scan(v interface{}) error {
	value, ok := v.(time.Time)
	if ok {
		*t = HTime{Time: value}
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}
